package protocol;


import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.*;
import io.netty.handler.codec.http.cookie.Cookie;
import io.netty.handler.codec.http.cookie.ServerCookieDecoder;
import io.netty.handler.codec.http.multipart.*;
import jodd.util.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @author yuzk
 * @date 2018/1/15
 */
public class Request {

    private static final Logger logger = LoggerFactory.getLogger(Request.class);

    public static final String METHOD_DELETE = HttpMethod.DELETE.name();
    public static final String METHOD_HEAD = HttpMethod.HEAD.name();
    public static final String METHOD_GET = HttpMethod.GET.name();
    public static final String METHOD_OPTIONS = HttpMethod.OPTIONS.name();
    public static final String METHOD_POST = HttpMethod.POST.name();
    public static final String METHOD_PUT = HttpMethod.PUT.name();
    public static final String METHOD_TRACE = HttpMethod.TRACE.name();

    private static final HttpDataFactory HTTP_DATA_FACTORY = new DefaultHttpDataFactory(DefaultHttpDataFactory.MINSIZE);

    private FullHttpRequest nettyRequest;

    private String path;
    private String ip;
    private Map<String, String> headers = new HashMap<String, String>();
    private Map<String, Object> params = new HashMap<String, Object>();
    private Map<String, Cookie> cookies = new HashMap<String, Cookie>();

    public Request(FullHttpRequest fullHttpRequest){
        path = fullHttpRequest.uri();

        QueryStringDecoder queryStringDecoder = new QueryStringDecoder(path);
        path = queryStringDecoder.path();
        headersAndCookies(fullHttpRequest);

        paramsGet(queryStringDecoder);
        HttpPostRequestDecoder decoder = null;
        try{
            decoder = new HttpPostRequestDecoder(HTTP_DATA_FACTORY, fullHttpRequest);
            paramsPost(decoder);
        }catch (Exception e){
            if(decoder != null) {
                decoder.destroy();
                decoder = null;
            }
        }
    }


    public Object getParamByKey(String key) {
        return params.get(key);
    }

    public String getPath() {
        return path;
    }

    public Map<String, Object> getParams() {
        return params;
    }

    /**
     * 填充头部信息和Cookies信息
     *
     * @param fullHttpRequest
     */
    private void headersAndCookies(FullHttpRequest fullHttpRequest) {
        HttpHeaders headers = fullHttpRequest.headers();
        for (Map.Entry<String, String> entry : headers) {
            this.headers.put(entry.getKey(), entry.getValue());
        }

        // Cookie
        final String cookieString = this.headers.get(HttpHeaderNames.COOKIE);
        if (StringUtil.isNotBlank(cookieString)) {
            final Set<Cookie> cookies = ServerCookieDecoder.LAX.decode(cookieString);
            for (Cookie cookie : cookies) {
                this.cookies.put(cookie.name(), cookie);
            }
        }

    }

    private void paramsGet(QueryStringDecoder decoder) {
        decoder.parameters().entrySet().forEach(param->{
            List<String> values = param.getValue();
            if(values != null && values.size() != 0){
                this.params.put(param.getKey(), values.size() == 1);
            }
        });
    }

    private void paramsPost(HttpPostRequestDecoder decoder){

        decoder.getBodyHttpDatas().forEach(data->{
            InterfaceHttpData.HttpDataType type = data.getHttpDataType();
            if(type == InterfaceHttpData.HttpDataType.Attribute){
                Attribute attribute = (Attribute) data;
                try{
                    this.params.put(attribute.getName(), attribute.getValue());
                }catch (Exception e){
                    logger.debug("get attribute error : " + e.getMessage());
                }
            }else if(type == InterfaceHttpData.HttpDataType.FileUpload){
                logger.debug("now doesn't support fileUpload");
            }
        });
    }

}
